package net.risesoft.y9public.service.user.impl;

import java.util.List;
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;

import net.risesoft.entity.Y9Manager;
import net.risesoft.entity.Y9Person;
import net.risesoft.id.IdType;
import net.risesoft.id.Y9IdGenerator;
import net.risesoft.y9.Y9Context;
import net.risesoft.y9.Y9LoginUserHolder;
import net.risesoft.y9.json.Y9JsonUtil;
import net.risesoft.y9.pubsub.constant.Y9OrgEventConst;
import net.risesoft.y9.pubsub.constant.Y9TopicConst;
import net.risesoft.y9.pubsub.message.Y9MessageOrg;
import net.risesoft.y9public.entity.tenant.Y9Tenant;
import net.risesoft.y9public.entity.user.Y9User;
import net.risesoft.y9public.repository.tenant.Y9TenantRepository;
import net.risesoft.y9public.repository.user.Y9UserRepository;
import net.risesoft.y9public.service.user.Y9UserService;

/**
 * @author dingzhaojun
 * @author qinman
 * @author mengjuhua
 * @date 2022/2/10
 */
@Service
@Transactional(value = "rsPublicTransactionManager", readOnly = true)
@RequiredArgsConstructor
public class Y9UserServiceImpl implements Y9UserService {

    private final KafkaTemplate<String, Object> y9KafkaTemplate;
    private final Y9UserRepository y9UserRepository;

    @Override
    public boolean checkCaid(String caid) {
        String tenantId = Y9LoginUserHolder.getTenantId();
        String personId = Y9LoginUserHolder.getPersonId();
        Y9User orgUser = this.findByCaidAndTenantId(personId, caid, tenantId);
        return orgUser == null;
    }

    @Override
    public boolean checkLoginName(Y9Person y9Person, String loginName) {
        String tenantId = y9Person.getTenantId();
        if (tenantId == null) {
            tenantId = Y9LoginUserHolder.getTenantId();
        }
        if (StringUtils.isNotBlank(loginName)) {
            Y9User orgUser = this.findByMobileAndTenantId(y9Person.getId(), loginName, tenantId);
            return orgUser == null;
        } else {
            return true;
        }
    }

    @Override
    public boolean checkMobile(Y9Person y9Person, String mobile) {
        String tenantId = y9Person.getTenantId();
        if (tenantId == null) {
            tenantId = Y9LoginUserHolder.getTenantId();
        }
        if (StringUtils.isNotBlank(mobile)) {
            Y9User orgUser = this.findByMobileAndTenantId(y9Person.getId(), mobile, tenantId);
            return orgUser == null;
        } else {
            return true;
        }
    }

    @Override
    @Transactional(readOnly = false)
    public void delete(String id) {
        Optional<Y9User> orgUser = y9UserRepository.findById(id);
        if (orgUser.isPresent()) {
            y9UserRepository.deleteById(id);

            String json = Y9JsonUtil.writeValueAsString(orgUser.get());
            Y9MessageOrg riseEvent = new Y9MessageOrg(json, Y9OrgEventConst.RISEORGEVENT_TYPE_DELETE_USER, Y9OrgEventConst.EVENT_TARGET_ALL, Y9LoginUserHolder.getTenantId());
            y9KafkaTemplate.send(Y9TopicConst.Y9_USER_EVENT, Y9JsonUtil.writeValueAsString(riseEvent));
        }
    }

    @Override
    @Transactional(readOnly = false)
    public void deleteByTenantId(String tenantId) {
        List<Y9User> y9UserList = y9UserRepository.findByTenantId(tenantId);
        y9UserRepository.deleteAll(y9UserList);
    }

    @Override
    public Y9User findByCaidAndTenantId(String personId, String caid, String tenantId) {
        return y9UserRepository.findByPersonIdNotAndCaidAndTenantId(personId, caid, tenantId);
    }

    @Override
    public Y9User findByLoginNameAndMobileAndTenantId(String loginName, String mobile, String tenantId) {
        return y9UserRepository.findByLoginNameAndMobileAndTenantId(loginName, mobile, tenantId);
    }

    @Override
    public Y9User findByLoginNameAndTenantId(String personId, String loginName, String tenantId) {
        return y9UserRepository.findByPersonIdIsNotAndLoginNameAndTenantId(personId, loginName, tenantId);
    }

    @Override
    public Y9User findByLoginNameAndTenantIdWithoutPersonId(String loginName, String tenantId) {
        return y9UserRepository.findByLoginNameAndTenantId(loginName, tenantId);
    }

    @Override
    public Y9User findByMobileAndTenantId(String personId, String mobile, String tenantId) {
        return y9UserRepository.findByPersonIdIsNotAndMobileAndTenantId(personId, mobile, tenantId);
    }

    @Override
    public Y9User findByPersonId(String personId) {
        return y9UserRepository.findByPersonId(personId);
    }

    @Override
    public Y9User findByPersonIdAndTenantId(String personId, String tenantId) {
        return y9UserRepository.findByPersonIdAndTenantId(personId, tenantId);
    }

    @Override
    public List<Y9User> listAll() {
        return y9UserRepository.findAll();
    }

    @Override
    public List<Y9User> listByGuidPathLike(String guidPath) {
        return y9UserRepository.findByGuidPathContaining(guidPath);
    }

    @Override
    public List<Y9User> listByLoginName(String loginName) {
        return y9UserRepository.findByLoginName(loginName);
    }

    @Override
    public List<Y9User> listByTenantId(String tenantId) {
        return y9UserRepository.findByTenantId(tenantId);
    }

    @Override
    @Transactional(readOnly = false)
    public Y9User save(Y9User orgUser) {
        Y9User saved = y9UserRepository.save(orgUser);

        String json = Y9JsonUtil.writeValueAsString(saved);
        Y9MessageOrg riseEvent = new Y9MessageOrg(json, Y9OrgEventConst.RISEORGEVENT_TYPE_UPDATE_USER, Y9OrgEventConst.EVENT_TARGET_ALL, Y9LoginUserHolder.getTenantId());
        y9KafkaTemplate.send(Y9TopicConst.Y9_USER_EVENT, Y9JsonUtil.writeValueAsString(riseEvent));
        return saved;
    }

    @Override
    public void sync() {
        List<Y9User> orgUsers = y9UserRepository.findAll();
        if (!orgUsers.isEmpty()) {
            String json = Y9JsonUtil.writeValueAsString(orgUsers);
            Y9MessageOrg riseEvent = new Y9MessageOrg(json, Y9OrgEventConst.RISEORGEVENT_TYPE_USER_SYNC, Y9OrgEventConst.EVENT_TARGET_ALL, Y9LoginUserHolder.getTenantId());
            y9KafkaTemplate.send(Y9TopicConst.Y9_USER_EVENT, Y9JsonUtil.writeValueAsString(riseEvent));
        }
    }

    @Override
    @Transactional(readOnly = false)
    public void syncManager(Y9Manager y9Manager) {
        String personId = y9Manager.getId();
        String tenantId = y9Manager.getTenantId();

        Y9TenantRepository y9TenantRepository = Y9Context.getBean(Y9TenantRepository.class);
        Y9Tenant y9Tenant = y9TenantRepository.findById(tenantId).orElse(null);

        Y9User y9User = y9UserRepository.findByPersonIdAndTenantId(personId, tenantId);
        if (y9User == null) {
            y9User = new Y9User();
            y9User.setId(Y9IdGenerator.genId(IdType.SNOWFLAKE));
        }

        y9User.setTenantId(tenantId);
        y9User.setTenantName(y9Tenant != null ? y9Tenant.getName() : "");
        y9User.setTenantShortName(y9Tenant != null ? y9Tenant.getShortName() : "");
        y9User.setLoginName(y9Manager.getLoginName());
        y9User.setPassword(y9Manager.getPassword());
        y9User.setPersonId(y9Manager.getId());
        y9User.setEmail(y9Manager.getEmail());
        y9User.setMobile(y9Manager.getMobile());
        y9User.setSex(y9Manager.getSex());
        y9User.setCaid(null);
        y9User.setWeixinId(null);
        y9User.setGuidPath(y9Manager.getGuidPath());
        y9User.setOrderedPath(null);
        y9User.setDn(y9Manager.getDn());
        y9User.setManagerLevel(y9Manager.getManagerLevel());

        y9User.setName(y9Manager.getName());
        y9User.setParentId(y9Manager.getParentId());
        y9User.setAvator(y9Manager.getAvator());
        y9User.setPersonType("deptPerson");
        y9User.setOriginal(true);
        y9User.setOriginalId(null);
        y9User.setRoles(null);
        y9User.setPositionId(null);
        y9User.setGlobalManager(y9Manager.getGlobalManager());
        y9UserRepository.save(y9User);
    }

    @Override
    @Transactional(readOnly = false)
    public void syncPerson(Y9Person person) {
        String personId = person.getId();
        String tenantId = person.getTenantId();

        Y9TenantRepository y9TenantRepository = Y9Context.getBean(Y9TenantRepository.class);
        Y9Tenant y9Tenant = y9TenantRepository.findById(tenantId).orElse(null);

        Y9User y9User = y9UserRepository.findByPersonIdAndTenantId(personId, tenantId);
        if (y9User == null) {
            y9User = new Y9User();
            y9User.setId(Y9IdGenerator.genId(IdType.SNOWFLAKE));
        }

        y9User.setTenantId(tenantId);
        if (null != y9Tenant) {
            y9User.setTenantName(y9Tenant.getName());
            y9User.setTenantShortName(y9Tenant.getShortName());
        }
        y9User.setLoginName(person.getLoginName());
        y9User.setPassword(person.getPassword());
        y9User.setPersonId(person.getId());
        y9User.setEmail(person.getEmail());
        y9User.setMobile(person.getMobile());
        y9User.setSex(person.getSex());
        y9User.setCaid(person.getCaid());
        y9User.setWeixinId(person.getWeixinId());
        y9User.setGuidPath(person.getGuidPath());
        y9User.setOrderedPath(person.getOrderedPath());
        y9User.setDn(person.getDn());
        y9User.setManagerLevel(0);

        y9User.setName(person.getName());
        y9User.setParentId(person.getParentId());
        y9User.setAvator(person.getAvator());
        y9User.setPersonType(person.getPersonType());
        y9User.setOriginal(person.getOriginal());
        y9User.setOriginalId(person.getOriginalId());
        y9User.setGlobalManager(false);
        y9User.setRoles(person.getRoles());
        y9UserRepository.save(y9User);

    }

    @Override
    @Transactional(readOnly = false)
    public void updateByTenantId(String tenantId, String tenantName, String tenantShortName) {
        List<Y9User> list = y9UserRepository.findByTenantId(tenantId);
        for (Y9User orgUser : list) {
            orgUser.setTenantName(tenantName);
            orgUser.setTenantShortName(tenantShortName);
            save(orgUser);
        }
    }
}
